#ifndef _HELIX_MESH_UTIL_H_
#define _HELIX_MESH_UTIL_H_

#include "../../Helix.h"
#include "../../HObject.h"
#include "Mesh.h"


namespace helix
{

	/**
	*	The MeshUtil class is responsible for performing operations on a Mesh object.  This is mostly
	*	things like saving/loading files, calculating normals, tangents, recalculating the order of
	*	vertices, sharing close vertices, etc...
	*/
	class MY_CLASS MeshUtil 
	{
	private:
		static bool getNextLine(ifstream *inFile,char *buff,int *lineNumber);

	public:
		/**	Loads a mesh from a file.  It will attempt to load the Mesh based on the file extension
		*	that is passed in.
		*	\param fileName name of the file to load
		*	\return The Mesh object if it was able to open and read the file.  Null if there was an error.
		*/
		static Mesh *loadFromFile(const char *fileName);

		/**	Loads a mesh from a file.  It assumes the file format is the Helix Model Format
		*	\param fileName name of the file to load
		*	\return The Mesh object if it was able to open and read the file.  Null if there was an error.
		*/
		static Mesh *loadFromHMF(const char *fileName);

		/** Saves a mesh to a file.  It attempt to save the Mesh based on the file extension that is
		*	passed in.
		*	\param mesh Mesh object to save
		*	\param fileName name of the file to save to
		*	\return A status code that determines whether the save was successful, or that some error
		*	occured.
		*/
//		static int saveToFile(Mesh *mesh, const char *fileName);

		/**	Deletes a Mesh object that was created by a call to a loadFrom* method.  This is the prefered
		*	way to delete a Mesh that was created by the MeshUtil class.
		*	\param the mesh to delete
		*/
		static void deleteMesh(Mesh *mesh);

		/** Uniformly scales the vertices of the mesh by some factor about the origin of the mesh.
		*	This method will change the internal values of the Mesh, so be careful to set a scaleFactor
		*	that will not put the Mesh in an unusable state.
		*	\param mesh The mesh to perform the scale operation on.
		*	\param scaleFactor The amount to factor the mesh by.  Since it is scaled equally in all
		*	directions, there is no need to recalculate vertex normals.
		*	\note setting a negative scaleFactor will cause unpredictable results, especially 
		*	with surface normals.  Essentially, they will point the wrong way and you might get
		*	inconsistent lighting.
		*	\note setting a scaleFactor of zero will cause the mesh data to scale to a single point.
		*	Once the data is in this state, it cannot be restored again by scaling.
		*/
		static void scaleVertices(Mesh *mesh,float scaleFactor);

		/** Automatically merges similar vertices and averages them to produce a smoothing effect.
		*	
		*	For quickest results, you should remove redundant vertices and texture coordinates before performing
		*	this operation.
		*
		*	The calculation will average the smoothable vertice's adjacent face normals.  This average will then
		*   be set as the vertex's normal.  If tangent and bitangent data exists, it will be updated as well. 
		*	
		*	\param mesh the mesh object to perform the operation on
		*	\param angleDeg This is the maximum angle (in degrees) between two vertice's normal elements that 
		*	cause a smooth operation.  
		*
		*	\note In order for two vertices to be smoothed, they must meet all of the criteria from the parameters.
		*	The vertices, texture coordinates, other data must be within the specified range. The face normals
		*	of all touching faces need to be within the specified angles.
		*/
		static void autoSmooth(Mesh *mesh,float angleDeg);

		/**	This method will combine vertices that are within certain distances of each other. The resulting
		*	vertices will all be set to the average.
		*
		*	\param mesh the mesh object to perform the operation on
		*	\param vertDist The maximum distance between vertices for them to be considered the same.
		*	\param texCoordDist The maximum distance between texture coordinates for them to be considered the same.
		*	\param otherDataDist The maximum distance between other data types for them to be considered the same.
		*
		*/
		static void removeDuplicateVerts(Mesh *mesh,float vertDist,float texCoordDist,float otherDataDist);

		bool SetSmooth();						//sets all vertices to smooth
		bool SetSolid();						//sets all vertices to solid (all vertex normals in triangle are same)
		bool CalculateTSMatrices();				//calculates the tangent space matrices of all the vertices
	};

}

#endif

